
pub fn fib_recursive(n: u64) -> u64 {
	match n {
		0 => 0,
		1|2 => 1,
		_ => fib_recursive(n-1) + fib_recursive(n-2) 
	}
} 


pub fn fib_deduce(n: i32) -> u64 {
	if n < 0 {
		panic!("{} is negative!", n);
	} else if n == 0 {
		panic!("zero is not a right argument to fibonacci()!");
	} else if n == 1 {
		return 1;
	}

	let mut sum = 0;
	let mut last = 0;
	let mut curr = 1;
	for _i in 1..n {
		sum = last + curr;
		last = curr;
		curr = sum;
	}
	sum
	
}


pub fn fib_memo(n: usize) -> u32 {
	let mut v = vec![0u32; (n + 1) as usize];
	return helper(&mut v, n);
}
fn helper(v: &mut Vec<u32>, n: usize) -> u32 {
	if n == 1 || n == 2 {
		return 1;
	}
	if v[n] != 0 {
		return v[n];
	} else {
		v[n] = helper(v, n-1) + helper(v, n-2);
		return v[n];
	}
}


#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_fib() {
        assert_eq!(fib_recursive(5), 5);
        assert_eq!(fib_deduce(5), 5);
		println!("f(5) = {}",fib_memo(5));
		assert_eq!(fib_memo(5), 5);
    }
}
